package com.kds.changzhou.handler;

import com.kds.changzhou.data.Gateway;
import com.kds.changzhou.data.Report;
import com.kds.changzhou.message.inbound.ResultMessage;
import com.kds.changzhou.message.outboud.AbstractOutBoundMessage;
import com.kds.changzhou.netty.TcpClient;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author 孔德嵩
 */
@Slf4j
public class ResultHandler extends SimpleChannelInboundHandler<ResultMessage> {


    static final String PASS = "pass";

    private ScheduledFuture<?> dataSubmitTask;

    private ScheduledFuture<?> heartbeatTask;


    private HandlerConfig handlerConfig;

    public ResultHandler(HandlerConfig handlerConfig) {
        this.handlerConfig = handlerConfig;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ResultMessage msg) throws Exception {

        String result = msg.getResult();

        boolean authenticated = isAuthenticated(result);

        Attribute GATE_WAY = ctx.channel().attr(TcpClient.GATE_WAY_KEY);

        Gateway gateway = (Gateway) GATE_WAY.get();

        if (authenticated) {
            log.info("采集器[{}_{}]已通过身份验证，开始发送报文数据", gateway.getBuildingCode(), gateway.getGatewayId());
            ctx.channel().attr(AttributeKey.valueOf("auth")).set(true);

            dataSubmitTask = ctx.channel().eventLoop().scheduleAtFixedRate(() -> {

                AbstractOutBoundMessage reportMessage = handlerConfig.getOutBoundMessageFactory().buildReportMessage();
                log.info("采集器[{}_{}]执行定时任务,查询Redis中的fid数据", gateway.getBuildingCode(), gateway.getGatewayId());
                Report report;
                try {
                    report = handlerConfig.getDataQueryService().makeReport(gateway);
                    reportMessage.setData(report);
                    ctx.writeAndFlush(reportMessage);
                } catch (Exception e) {
                    log.info("采集器[{}_{}]定时任务执行发送report失败，因数据查询问题跳过本次数据上传", gateway.getBuildingCode(), gateway.getGatewayId());
                    log.error(ExceptionUtils.getStackTrace(e));
                }

            }, 1, 15, TimeUnit.MINUTES);

            heartbeatTask = ctx.channel().eventLoop().scheduleAtFixedRate(() -> {

                AbstractOutBoundMessage heartbeatMessage = handlerConfig.getOutBoundMessageFactory().buildHeartbeatMessage();
                Map data = new HashMap<>();
                data.put("buildingCode", msg.getBuildingCode());
                data.put("gatewayId", msg.getGatewayId());
                heartbeatMessage.setData(data);


                ctx.writeAndFlush(heartbeatMessage);

            }, 30, 60, TimeUnit.SECONDS);

        } else {
            log.info("采集器[{}_{}]身份验证失败", gateway.getBuildingCode(), gateway.getGatewayId());
            ctx.fireChannelInactive();
        }

    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) {

        Attribute GATE_WAY = ctx.channel().attr(TcpClient.GATE_WAY_KEY);

        Gateway gateway = (Gateway) GATE_WAY.get();

        log.info("采集器[{}_{}]与服务器连接中断", gateway.getBuildingCode(), gateway.getGatewayId());

        // 在连接关闭时取消定时任务
        if (dataSubmitTask != null) {
            dataSubmitTask.cancel(true);
        }
        if (heartbeatTask != null) {
            heartbeatTask.cancel(true);
        }
        ctx.fireChannelInactive();
    }

    private boolean isAuthenticated(String result) {

        return PASS.equals(result);
    }


}
